home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Magazine / C_Tutorial / Part-5 / multiwin0.c < prev    next >
C/C++ Source or Header  |  1997-09-30  |  12KB  |  439 lines

  1. #include<exec/libraries.h>
  2. #include<intuition/intuition.h>
  3. #include<utility/tagitem.h>
  4. #include<graphics/text.h>
  5. #include<graphics/rastport.h>
  6. #include<intuition/screens.h>
  7. #include<libraries/gadtools.h>
  8.  
  9. #include<string.h>
  10. #include<stdio.h>
  11.  
  12. #include<clib/exec_protos.h>
  13. #include<clib/graphics_protos.h>
  14. #include<clib/intuition_protos.h>
  15. #include<clib/gadtools_protos.h>
  16.  
  17. /* The library base global variables */
  18. /* (The different style of opening libraries requires these to be initialised to NULL) */
  19. struct Library* GfxBase = NULL;
  20. struct Library* IntuitionBase = NULL;
  21. struct Library* GadToolsBase = NULL;
  22.  
  23. /* The global handle on the palette gadget */
  24. struct Gadget* palgad = NULL;
  25. /* Global record of foreground pen */
  26. UBYTE pen;
  27. /* Global records of our windows */
  28. struct Window* drawwin;
  29. struct Window* toolwin;
  30. /* Global record of title bar height */
  31. int offtop;
  32.  
  33. /* Need to give prototypes for our functions */
  34. void handleIDCMP();
  35. void setupWindows();
  36. void createWindows(struct Gadget*, struct Screen*, struct Menu*);
  37. int openLibs();
  38. void closeLibs();
  39. struct Menu* createMenuStrip(APTR);
  40. void setFgPen(int);
  41. void doGadgetUp(struct IntuiMessage*);
  42. int doMenuPick(struct Window*, struct IntuiMessage*);
  43.  
  44. /* Some constants for the position and size of our gadget */
  45. #define MYBUT_LEFT        (10)
  46. #define MYBUT_TOP            (5)
  47. #define MYBUT_WIDTH        (80)
  48. #define MYBUT_HEIGHT    (12)
  49. #define MYBUT_TEXT        "Next Pen"
  50. #define MYBUT_ID            (0)
  51.  
  52. #define MYPAL_LEFT        (170)
  53. #define MYPAL_TOP            (1)
  54. #define MYPAL_WIDTH        (109)
  55. #define MYPAL_HEIGHT    (19)
  56. #define MYPAL_TEXT        "Colour:"
  57. #define MYPAL_ID            (1)
  58. #define MYPAL_DEPTH        (4)
  59.  
  60. /* The top gap required around the gadgets */
  61. #define MYTOPGAP      (21)
  62.  
  63. /* The initial pen colour */
  64. #define MYINITPEN            (1)
  65.  
  66. /* The start of the program */
  67. void main()
  68. {
  69.     /* Use a different style of opening libraries... */
  70.     if(openLibs())
  71.     {
  72.         /* Now do the real work */
  73.         setupWindows();
  74.     }
  75.     /* Matched call to close libraries */
  76.     closeLibs();
  77. }
  78.  
  79. /* Try to open all the libraries -- return TRUE on success */
  80. int openLibs()
  81. {
  82.     if((GfxBase = OpenLibrary("graphics.library",37)) == NULL)
  83.     {
  84.         printf("Error: could not open graphics.library\n");
  85.         return FALSE;
  86.     }
  87.     if((IntuitionBase = OpenLibrary("intuition.library",37)) == NULL)
  88.     {
  89.         printf("Error: could not open intuition.library\n");
  90.         return FALSE;
  91.     }
  92.     if((GadToolsBase = OpenLibrary("gadtools.library",37)) == NULL)
  93.     {
  94.         printf("Error: could not open gadtools.library\n");
  95.         return FALSE;
  96.     }
  97.   return TRUE;
  98. }
  99.  
  100. /* Close any open library */
  101. void closeLibs()
  102. {
  103.     if(GadToolsBase)
  104.         CloseLibrary(GadToolsBase);
  105.     if(IntuitionBase)
  106.         CloseLibrary(IntuitionBase);
  107.     if(GfxBase)
  108.         CloseLibrary(GfxBase);
  109. }
  110.  
  111. /* Setup the windows -- do the GadTools stuff */
  112. void setupWindows()
  113. {
  114.     struct Screen* scr;
  115.     UWORD pens[] = { ~0 };
  116.     /* Try to open a new screen with 16 colours (four bitplanes deep) */
  117.     if(scr = OpenScreenTags(NULL,
  118.                                                     SA_Depth,    4,
  119.                                                     /* Enable 3D look by specifying SA_Pens */
  120.                                                     SA_Pens,    pens,
  121.                                                     SA_Title,    "Hello World Painter",
  122.                                                     TAG_DONE))
  123.     {
  124.         APTR vinfo;
  125.         /* Get the visual info so GadTools can render the gadgets nicely */
  126.         if(vinfo = GetVisualInfo(scr, TAG_DONE))
  127.         {
  128.             /* We can initialise glist in its declaration */
  129.             struct Gadget* glist = NULL;
  130.             struct Gadget* gad;
  131.             int offleft;
  132.             struct NewGadget newgad;
  133.             /* Initialised structure declaration: describes 8pt Topaz font */
  134.             struct TextAttr topazFont = { "topaz.font", 8, 0, 0, };
  135.             /* Start a GadTools gadget list */
  136.             gad = CreateContext(&glist);
  137.             /* The offsets of our window borders */
  138.             offleft = scr->WBorLeft;
  139.             offtop = scr->WBorTop + (scr->Font->ta_YSize + 1);
  140.  
  141.             /* Setup our first gadget */
  142.             newgad.ng_TextAttr         = &topazFont;
  143.             newgad.ng_VisualInfo     = vinfo;
  144.             newgad.ng_LeftEdge         = MYBUT_LEFT + offleft;
  145.             newgad.ng_TopEdge         = MYBUT_TOP + offtop;
  146.             newgad.ng_Width             = MYBUT_WIDTH;
  147.             newgad.ng_Height             = MYBUT_HEIGHT;
  148.             newgad.ng_GadgetText    = MYBUT_TEXT;
  149.             newgad.ng_GadgetID        = MYBUT_ID;
  150.             newgad.ng_Flags                = 0;
  151.             /* Now create it and add it to our list */
  152.             gad = CreateGadget(BUTTON_KIND, gad, &newgad, TAG_END);
  153.  
  154.             /* Setup our second gadget */
  155.             /* (We can reuse newgad, and just change the different bits) */
  156.             newgad.ng_LeftEdge         = MYPAL_LEFT + offleft;
  157.             newgad.ng_TopEdge         = MYPAL_TOP + offtop;
  158.             newgad.ng_Width             = MYPAL_WIDTH;
  159.             newgad.ng_Height             = MYPAL_HEIGHT;
  160.             newgad.ng_GadgetText    = MYPAL_TEXT;
  161.             newgad.ng_GadgetID        = MYPAL_ID;
  162.             newgad.ng_Flags                = 0;
  163.             /* Now create it and add it to our list */
  164.             if(gad = CreateGadget(PALETTE_KIND, gad, &newgad,
  165.                                                         /* Initially selected pen */
  166.                                                         GTPA_Color, MYINITPEN,
  167.                                                         /* Depth: 2 to the power MYPAL_DEPTH colours */
  168.                                                         GTPA_Depth, MYPAL_DEPTH,
  169.                                                         /* Gadget will indicate selection */
  170.                                                         GTPA_IndicatorWidth, 16,
  171.                                                         TAG_DONE))
  172.             {
  173.                 struct Menu* menustrip;
  174.                 /* Remember gadget pointer so we can affect it in message handler */
  175.                 palgad = gad;
  176.                 if(menustrip = createMenuStrip(vinfo))
  177.                     /* If succeeded then all gadgets and menus created */
  178.                     createWindows(glist, scr, menustrip);
  179.                 FreeMenus(menustrip);
  180.             }
  181.             else
  182.                 printf("Error: could not create gadget(s)\n");
  183.             /* Free all the gadgets that were created */
  184.             FreeGadgets(glist);
  185.             FreeVisualInfo(vinfo);
  186.         }
  187.         else
  188.             printf("Error: could not get visual info\n");
  189.         CloseScreen(scr);
  190.     }
  191.     else
  192.         printf("Error: could not create screen\n");
  193. }
  194.  
  195. /* Create the menu strip, using GadTools menu functions */
  196. struct Menu* createMenuStrip(APTR vinfo)
  197. {
  198.     /* The description of our menus */
  199.     struct NewMenu mymenu[] =
  200.     {
  201.         { NM_TITLE, "Project",        0,            0, 0, 0,},
  202.         {  NM_ITEM,        "Quit",                "Q",    0, 0, 0,},
  203.         { NM_TITLE, "Pen",                0,            0, 0, 0,},
  204.         {  NM_ITEM,        "Next",                "N",    0, 0, 0,},
  205.         {  NM_ITEM,        "Prev",                "P",    0, 0, 0,},
  206.         {  NM_ITEM,        NM_BARLABEL,    0,        0, 0, 0,},
  207.         {  NM_ITEM,        "Reset",            "R",    0, 0, 0,},
  208.         {   NM_END, NULL,                    0,            0, 0, 0,},
  209.     };
  210.     struct Menu* menustrip;
  211.     if (menustrip = CreateMenus(mymenu, TAG_END))
  212.     {
  213.         if (LayoutMenus(menustrip, vinfo, TAG_END))
  214.             /* Succeeded, so return menu strip */
  215.             return menustrip;
  216.         else
  217.         {
  218.             /* Failed, so must deallocate before returning */
  219.             FreeMenus(menustrip);
  220.             printf("Error: could not layout menus\n");
  221.         }
  222.     }
  223.     else
  224.         printf("Error: could not create menu strip\n");
  225.     /* Failed, so return NULL */
  226.     return NULL;
  227. }
  228.  
  229. /* Actually open the window, in the normal way */
  230. void createWindows(struct Gadget* glist, struct Screen* scr, struct Menu* menustrip)
  231. {
  232.     /* Open our drawing window */
  233.     if(drawwin = OpenWindowTags(NULL,
  234.                                                             WA_Left,                    0,
  235.                                                             WA_Top,                        0,
  236.                                                             /* Make the window the same size as the screen */
  237.                                                             WA_Width,                    scr->Width,
  238.                                                             WA_Height,                scr->Height,
  239.                                                             WA_Flags,                    WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_REPORTMOUSE,
  240.                                                             WA_IDCMP,                    IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK,
  241.                                                             WA_CustomScreen,    scr,
  242.                                                             TAG_DONE,                    0))
  243.     {
  244.         /* Attach menu strip to drawing window */
  245.         if(SetMenuStrip(drawwin, menustrip))
  246.         {
  247.             /* The minimal height of our tool window */
  248.             int h = MYTOPGAP + offtop + scr->WBorBottom;
  249.             /* Open our tool window */
  250.             if(toolwin = OpenWindowTags(NULL,
  251.                                                                     WA_Left,                    0,
  252.                                                                     WA_Top,                        scr->Height - h,
  253.                                                                     /* Make the window sit in the bottom of the screen */
  254.                                                                     WA_Width,                    scr->Width,
  255.                                                                     WA_Height,                h,
  256.                                                                     WA_Flags,                    WFLG_CLOSEGADGET | WFLG_DRAGBAR,
  257.                                                                     WA_IDCMP,                    IDCMP_CLOSEWINDOW | BUTTONIDCMP | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
  258.                                                                     WA_Gadgets,                glist,
  259.                                                                     WA_CustomScreen,    scr,
  260.                                                                     WA_Title,                    "Tools",
  261.                                                                     TAG_DONE,                    0))
  262.             {
  263.                 /* Attach menu strip to tool window, as well */
  264.                 if(SetMenuStrip(toolwin, menustrip))
  265.                 {
  266.                     /* Let GadTools refresh its bits of the tool window */
  267.                     GT_RefreshWindow(toolwin, NULL);
  268.                     /* Now handle messages from both windows */
  269.                     handleIDCMP();
  270.                     /* Remove menu strip from tool window */
  271.                     ClearMenuStrip(toolwin);
  272.                 }
  273.                 else
  274.                     printf("Error: could not attach menus to tool window\n");
  275.                 CloseWindow(toolwin);
  276.             }
  277.             else
  278.                 printf("Error: could not open tool window\n");
  279.             /* Remove menu strip from drawing window */
  280.             ClearMenuStrip(drawwin);
  281.         }
  282.         else
  283.             printf("Error: could not attach menus to drawing window\n");
  284.         CloseWindow(drawwin);
  285.     }
  286.     else
  287.         printf("Error: could not open drawing window\n");
  288. }
  289.  
  290. /* Our message handling code */
  291. void handleIDCMP()
  292. {
  293.     char* text = "Hello World!";
  294.     int going = TRUE;
  295.     int drawing = FALSE;
  296.     ULONG drawsig, toolsig, gotsig;
  297.     drawsig = 1 << drawwin->UserPort->mp_SigBit;
  298.     toolsig = 1 << toolwin->UserPort->mp_SigBit;
  299.     setFgPen(MYINITPEN);
  300.     /* Set the drawing mode to draw only the foreground of text, not the background */
  301.     SetDrMd(drawwin->RPort, JAM1);
  302.     while(going)
  303.     {
  304.         struct IntuiMessage* intuimsg;
  305.         /* Wait for messages to arrive */
  306.         gotsig = Wait(drawsig | toolsig);
  307.         /* Messages have arrived: loop through all of them */
  308.         /* Check messages from the drawing window first */
  309.         if(gotsig & drawsig)
  310.         {
  311.             while(intuimsg = GT_GetIMsg(drawwin->UserPort))
  312.             {
  313.                 /* Act on this message... */
  314.                 switch(intuimsg->Class)
  315.                 {
  316.                 case IDCMP_MOUSEBUTTONS:
  317.                     switch(intuimsg->Code)
  318.                     {
  319.                     case SELECTDOWN:
  320.                         drawing = TRUE;
  321.                         break;
  322.                     case SELECTUP:
  323.                         drawing = FALSE;
  324.                         break;
  325.                     }
  326.                     /* break; omitted so we draw on click, too */
  327.                 case IDCMP_MOUSEMOVE:
  328.                     if(drawing)
  329.                     {
  330.                         Move(drawwin->RPort, intuimsg->MouseX, intuimsg->MouseY);
  331.                         Text(drawwin->RPort, text, strlen(text));
  332.                     }
  333.                     break;
  334.                 case IDCMP_MENUPICK:
  335.                     going = doMenuPick(drawwin, intuimsg);
  336.                     break;
  337.                 }
  338.                 /* Reply when finished with message */
  339.                 GT_ReplyIMsg(intuimsg);
  340.             }
  341.         }
  342.         /* Now check messages from the tool window */
  343.         if(gotsig & toolsig)
  344.         {
  345.             while(intuimsg = GT_GetIMsg(toolwin->UserPort))
  346.             {
  347.                 /* Act on this message... */
  348.                 switch(intuimsg->Class)
  349.                 {
  350.                 case IDCMP_CLOSEWINDOW:
  351.                     going = FALSE;
  352.                     break;
  353.                 case IDCMP_REFRESHWINDOW:
  354.                     /* You *MUST* remember to ask for and handle these refresh messages */
  355.                     GT_BeginRefresh(toolwin);
  356.                     GT_EndRefresh(toolwin, TRUE);
  357.                     break;
  358.                 case IDCMP_GADGETUP:
  359.                     doGadgetUp(intuimsg);
  360.                     break;
  361.                 case IDCMP_MENUPICK:
  362.                     going = doMenuPick(toolwin, intuimsg);
  363.                     break;
  364.                 }
  365.                 /* Reply when finished with message */
  366.                 GT_ReplyIMsg(intuimsg);
  367.             }
  368.         }
  369.     }
  370. }
  371.  
  372. /* Set foreground pen of drawing window */
  373. void setFgPen(int value)
  374. {
  375.     /* Wrap when reached the end of the palette gadget's colours */
  376.     pen = value % (1<<MYPAL_DEPTH);
  377.     SetAPen(drawwin->RPort, pen);
  378.     /* If the palette gadget has been made, update it with new pen value */
  379.     if(palgad)
  380.         GT_SetGadgetAttrs(palgad, toolwin, NULL, GTPA_Color, pen, TAG_DONE);
  381. }
  382.  
  383. /* Process IDCMP_GADGETUP event */
  384. void doGadgetUp(struct IntuiMessage* intuimsg)
  385. {
  386.     struct Gadget* gad = (struct Gadget*)(intuimsg->IAddress);
  387.     switch(gad->GadgetID)
  388.     {
  389.     case MYBUT_ID:
  390.         /* Our button was clicked!  Set foreground to next pen colour */
  391.         setFgPen(pen+1);
  392.         break;
  393.     case MYPAL_ID:
  394.         /* Our palette gadget was clicked!  Set foreground to gadget colour */
  395.         setFgPen(intuimsg->Code);
  396.         break;
  397.     }
  398. }
  399.  
  400. /* Process IDCMP_MENUPICK event */
  401. int doMenuPick(struct Window* win, struct IntuiMessage* intuimsg)
  402. {
  403.     UWORD menuCode, menuNumber, itemNumber;
  404.     /* Loop over all the menu selections in the menu code */
  405.     for(menuCode = intuimsg->Code;
  406.             menuCode != MENUNULL;
  407.             menuCode = ItemAddress(win->MenuStrip, menuCode)->NextSelect)
  408.     {
  409.         /* Extract the menu number and menu item number from the menu code */
  410.         menuNumber = MENUNUM(menuCode);
  411.         itemNumber = ITEMNUM(menuCode);
  412.         /* Now decide what to do based on what menu item was selected */
  413.         switch(menuNumber)
  414.         {
  415.         case 0:  /* Project menu */
  416.             /* Only one item: Quit */
  417.             if(itemNumber == 0)
  418.                 return FALSE;  /* Stop going */
  419.             break;
  420.         case 1:  /* Pen menu */
  421.             switch(itemNumber)
  422.             {
  423.             case 0:  /* Next */
  424.                 setFgPen(pen+1);
  425.                 break;
  426.             case 1:  /* Prev */
  427.                 setFgPen(pen-1);
  428.                 break;
  429.             case 3:  /* Reset (item 2 is the bar!) */
  430.                 setFgPen(MYINITPEN);
  431.                 break;
  432.             }
  433.             break;
  434.         }
  435.     }
  436.     /* Keep going */
  437.     return TRUE;
  438. }
  439.